#include"Task.hpp"
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#include <iostream>
#include <string>



#define NUM 1024

const int n = 10;
extern vector<task_t> Task;
using namespace std;

//固定读4Bytes，根据任务码执行任务
//先描述
class channel
{
public:
    channel(int cmdfd, pid_t slaverid, string slavername)
    :_cmdfd(cmdfd)
    ,_slaverid(slaverid)
    ,_slavername(slavername)
    {}


public:
    int _cmdfd;     //发送任务的文件描述符，通过选择管道来选择进程
    pid_t _slaverid;    //子进程pid
    string  _slavername;     //子进程名，用于打印日志
};

void SlaverWork()
{
    int taskcode = 0;
    while(true)
    {
        read(0, &taskcode, sizeof(int));
       // cout << "i am " << c._slavername << ", pid is " << c._slaverid;
        cout << "child-" << getpid() << "-"; 
        Task[taskcode]();
        sleep(1);
    }
}

void InitProcessPool(vector<channel>* channels)
{
    int pipefd[2];  
    for(int i = 0; i < n; i++)
    {
        if(pipe(pipefd) == -1)
        {
            perror("pipe erroe\n");
            exit(1);
        }

        //cout << pipefd[0] << " " << pipefd[1] << endl;

        pid_t id = fork();
        if(id < 0)
        {
            perror("fork error\n");
            exit(2);
        }
        else if(id == 0) //child
        {
            close(pipefd[1]);   //每个子进程关闭自己的写端
            close(0);
            dup2(pipefd[0],0);
            SlaverWork();
            //exit(0);
        }

        //father
        close(pipefd[0]);   //父进程关闭自己的读端
        channels->push_back(channel(pipefd[1], id, "process_"+to_string(i)));        //mistake echo: "process_"+ i：char*指针+i
    }

}


int main()
{
    //再组织
    vector<channel> channels;
    int cmdcode = 0;

    srand((unsigned int)time(0));

    //初始化
    InitProcessPool(&channels);
    
    while(true)
    {
        //选择进程
        int proindex = rand() % channels.size();

        //选择任务
        cmdcode = rand() % Task.size();
        
        //channels[proindex]._cmdfd:所选进程对应的管道文件
        write(channels[proindex]._cmdfd, &cmdcode, sizeof(int));
        //SlaverWork(channels[proindex]);
        sleep(1);        
    }


    // for(auto e : channels)
    // {
    //     cout << e._cmdfd << ": " << e._slaverid << "-"<< e._slavername << endl;
    // }
    
    return 0;
}

//注：pipefd和管道文件的struct file存不存再无关，struct file的创建与回收由操作系统决定
//    pipefd仅将管道文件的读端和写端的fd带出